﻿using System;
using Messegers;
using UnityEngine;
using UnityEngine.Events;

namespace DL.UI
{
    public abstract class AbstractPage : MonoBehaviour
    {
        //不是很好用
        // public AbstractModel _view;
        //
        // protected AbstractModel View
        // {
        //     get
        //     {
        //         if (_view == null)
        //         {
        //             _view = GetComponent<AbstractModel>();
        //             if (_view == null)
        //             {
        //                 Debug.LogError("RootModelView not exit");
        //             }
        //         }
        //
        //         return _view;
        //     }
        // }

        [NonSerialized] public PageType PageType;

        // protected virtual void Awake()
        // {
        //     if (View != null)
        //     {
        //         View.SetContext(this);
        //     }
        // }
        
        [NonSerialized] public string PageName;

        public PageParam Param = new PageParam();
        public Transform ChildrenPageParent;
        [NonSerialized] public AbstractPage ParentPage;
        private bool _inited = false;
        [NonSerialized] public bool Shown = false;


#if UNITY_EDITOR
        public static bool ShowLog = true;
#else
         public static bool ShowLog = false;
#endif
        public class PageEvent : UnityEvent<AbstractPage>
        {
        }

        private void Init()
        {
            if (!_inited)
            {
                OnCreate();
                _inited = true;
            }
        }


        public void Show(string pageName, PageType pageType, PageParam param)
        {
            if (ShowLog)
            {
                Debug.LogFormat("ShowPage [{0}]: {1} , {2}", pageType, pageName, Shown);
            }

            Param.MergeStringKeys(param);
            Param.StripKeysWithNullValues();
            PageName = pageName;
            PageType = pageType;
            if (Shown)
            {
                OnRefresh();
                return;
            }

            Init();
            SetActive(gameObject, true);
            Shown = true;
            BringIn();
        }

        protected bool IsReturning;

        public void ShowByReturn()
        {
            if (Shown)
            {
                OnRefresh();
                return;
            }

            SetActive(gameObject, true);
            Shown = true;
            IsReturning = true;
            BringIn();
        }

        /// <summary>
        /// 仅用于界面显示后的数据刷新
        /// </summary>
        public virtual void OnRefresh()
        {
        }

        [NonSerialized] public AbstractPage CurrentShownTabPage;

        public virtual AbstractPage ShowTabPage(string pageName, PageParam param = null)
        {
            if (ChildrenPageParent == null)
            {
                var children = transform.GetComponentsInChildren<Transform>();
                foreach (var child in children)
                {
                    if (child.name == "SubPage")
                    {
                        ChildrenPageParent = child;
                    }
                }
            }

            if (CurrentShownTabPage != null && CurrentShownTabPage.PageName != pageName)
            {
                CurrentShownTabPage.Hide();
                CurrentShownTabPage = null;
            }

            var page = PageMgr.GetTabPage(pageName, ChildrenPageParent);
            if (page != null)
            {
                page.ParentPage = this;
                CurrentShownTabPage = page;
                if (IsReturning)
                {
                    CurrentShownTabPage.ShowByReturn();
                }
                else
                {
                    CurrentShownTabPage.Show(pageName, PageType.TabPage, param);
                }

                return CurrentShownTabPage;
            }

            return null;
        }


        public PageEvent DissmissEvent = new PageEvent();
        public PageEvent FinishDissmissEvent = new PageEvent();


        public PageEvent BringInEvent = new PageEvent();
        public PageEvent FinisBringInEvent = new PageEvent();

        public void Hide(bool eraseOnPathPoint = false)
        {
            if (ShowLog)
            {
                Debug.Log("HidePage : " + PageName);
            }

            if (eraseOnPathPoint)
            {
                if (PageCaches.Exist())
                {
                    PageCaches.Inst.CurrentPathPoint.DeRecordPage(PageName, PageType);
                }
            }

            if (!IsFinishedBringIn)
            {
                IsFinishedBringIn = true;
            }
            
            if (_inited && Shown && IsFinishedBringIn)
            {
                if (CurrentShownTabPage != null)
                {
                    CurrentShownTabPage.Hide();
                    CurrentShownTabPage = null;
                }

                Dismiss();
            }
        }

        public void HideNow(bool eraseOnPathPoint = false)
        {
            Hide(eraseOnPathPoint);
        }

        private bool BringIning { get; set; }

        private void BringIn()
        {
            BringIning = true;
            IsFinishedBringIn = false;
            OnBringIn();
            BringInEvent.Invoke(this);
            FinishBringIn();

        }
        

        public bool IsFinishedBringIn { get; private set; }

        private void FinishBringIn()
        {
            if (BringIning)
            {
                IsFinishedBringIn = true;
                BringIning = false;
                OnFinishBringIn();
                FinisBringInEvent.Invoke(this);
            }

            IsReturning = false;
        }


        public bool Dismissing { get; private set; }

        private void Dismiss(bool destroyed = false)
        {
            Dismissing = true;
            OnDismiss(destroyed);
            DissmissEvent.Invoke(this);
            Messenger<string>.Broadcast(MessengerName.MSG_PageDismissEvt, PageName);
            FinishDismiss(destroyed);
        }



        private void FinishDismiss(bool destroyed)
        {
            if (Dismissing)
            {
                Dismissing = false;
                SetActive(gameObject, false);
                Shown = false;
                OnFinishDismiss(destroyed);
                FinishDissmissEvent.Invoke(this);
            }
        }

        private static void SetActive(GameObject go, bool state)
        {
            if (go.activeInHierarchy != state)
            {
                go.SetActive(state);
            }
        }

        public abstract void OnCreate();


        public abstract void OnBringIn();


        public virtual void OnFinishBringIn()
        {
        }

        public virtual void OnDismiss(bool destroyed)
        {
        }

        public virtual void OnFinishDismiss(bool destroyed)
        {
        }
        
        //动画,找个地方插入进去
        private void OnOpenTween()
        {
            
        }
        
        private void OnCloseTween()
        {
            
        }

        protected bool Destroying { get; private set; }

        public virtual void OnDestroy()
        {
            Destroying = true;

            if (!_appQuit)
            {
                if (_inited && Shown)
                {
                    Dismiss(true);
                }
            }
        }

        /// <summary>
        /// 手动点击关闭，需要移除记录
        /// </summary>
        protected virtual void OnTapClose()
        {
            Hide(true);
        }

        /// <summary>
        /// 移除本界面在路径节点中的信息
        /// </summary>
        public void EraseOnPathPoint()
        {
            PageCaches.Inst.CurrentPathPoint.DeRecordPage(PageName, PageType);
        }

        private bool _appQuit = false;

        private void OnApplicationQuit()
        {
            _appQuit = true;
        }
    }


    //public abstract class AbstractPage : MonoBehaviour
    //{
    //    public AbstractModel _model;

    //    protected AbstractModel Model
    //    {
    //        get
    //        {
    //            if (_model == null)
    //            {
    //                _model = GetComponent<AbstractModel>();
    //                if (_model == null)
    //                {
    //                    Debug.LogError("RootModelView not exit");
    //                }
    //            }

    //            return _model;
    //        }
    //    }

    //    protected void Awake()
    //    {
    //        if (Model != null)
    //        {
    //            Model.SetContext(this);
    //        }

    //    }

    //    [NonSerialized] public PageType PageType;

    //    public class PageEvent : UnityEvent<AbstractPage> { }

    //    public PageEvent DissmissEvent = new PageEvent();

    //    public PageEvent BringInEvent = new PageEvent();
    //    private bool _inited;

    //    private void Init()
    //    {
    //        if (!_inited)
    //        {
    //            OnCreate();
    //            _inited = true;
    //        }
    //    }

    //    protected abstract void OnCreate();

    //    public void Show(string pageName, PageType pageType, PageParam param)
    //    {
    //        Debug.LogFormat("ShowPage [{0}]: {1}", pageType, pageName);
    //        // Param.MergeStringKeys(param);
    //        // Param.StripKeysWithNullValues();
    //        // PageName = pageName;
    //        // PageType = pageType;
    //        // if (Shown)
    //        // {
    //        //     OnRefresh();
    //        //     return;
    //        // }
    //        //
    //        // Init();
    //        // SetActive(gameObject, true);
    //        // Shown = true;
    //        // BringIn();
    //    }

    //    public void ShowByReturn()
    //    {
    //        // if (ShowLog)
    //        // {
    //        //     Debug.LogFormat("Return Page [{0}]: {1}", PageType, PageName);
    //        // }
    //        // if (Shown)
    //        // {
    //        //     OnRefresh();
    //        //     return;
    //        // }
    //        //
    //        // SetActive(gameObject, true);
    //        // Shown = true;
    //        // IsReturning = true;
    //        // BringIn();
    //    }
}